Late answer but I can't resist.
Is X most classes into Y good or an anti-pattern?
In most cases, most rules, applied without thinking, will mostly go horribly wrong (including this one).
Let me tell you a story about the birth of an object amid the chaos of some down right, quick and dirty, procedural code that happened, not by design, but out of desperation.
My intern and I are pair programming to quickly create some throw away code to scrape a webpage. We have absolutely no reason to expect this code will live long, so we're just banging out something that works. We grab the whole page as a string and chop out the stuff we need in the most amazingly brittle way you could imagine. Don't judge. It works.
Now while doing this I created some static methods to do the chopping. My intern created a DTO class that was very much like your CatData
.
When I first looked at the DTO it bugged me. The years of damage Java has done to my brain made me recoil at the public fields. But we were working in C#. C# has no need of premature getters and setters to preserve your right to make the data immutable, or encapsulated later. Without changing the interface you can add them whenever you like. Maybe just so you can set a breakpoint. All without telling your clients a thing about it. Yea C#. Boo Java.
So I held my tongue. I watched as he used my static methods to initialize this thing before using it. We had about 14 of them. It was, ugly, but we had no reason to care.
Then we needed it in other places. We found ourselves wanting to copy and paste the code. 14 lines of initialization being flung around. It was starting to get painful. He hesitated and asked me for ideas.
Reluctantly I asked, "would you consider an object?"
He looked back at his DTO and screwed up his face in confusion. "It is an object".
"I mean a real object"
"Huh?"
"Let me show you something. You decide if it's useful"
I chose a new name and quickly whipped up something that looked a little like this:
public class Cat{
Cat(string catPage) {
this.catPage = catPage
}
private readonly string catPage;
public string name() { return chop("name prefix", "name suffix"); }
public string weight() { return chop("weight prefix", "weight suffix"); }
public string image() { return chop("image prefix", "image suffix"); }
private string chop(string prefix, string suffix) {
int start = catPage.indexOf(prefix) + prefix.Length;
int end = catPage.indexOf(suffix);
int length = end - start;
return catPage.Substring(start, length);
}
}
This did nothing the static methods weren't already doing. But now I'd sucked the 14 static methods into a class where they could be alone with the data they worked on.
I didn't force my intern to use it. I just offered it and let him decide if he wanted to stick with the static methods. I went home thinking he'd probably stick to what he already had working. The next day I found he was using the object in a bunch of places. It decluttered the rest of the code which was still ugly and procedural but this bit of complexity was now hidden from us behind an object. It was a little better.
Now sure every time you access this it's doing a fair bit of work. A DTO is a nice fast cached value. I worried about that but realized I could add the caching if we ever needed without touching any of the using code. So I'm not going to bother until we care.
Am I saying you should always stick to OO objects over DTO's? No. DTO's shine when you need to cross a boundary that keeps you from moving methods. DTO's have their place.
But so do OO objects. Learn how to use both tools. Learn what each costs. Learn to let the problem, the situation, and the intern decide. Dogma is not your friend here.
Since my answer is already ridiculously long let me disabuse you of some misconceptions with a review of your code.
For example, a class usually have class members and methods, eg:
public class Cat{
private String name;
private int weight;
private Image image;
public void printInfo(){
System.out.println("Name:"+this.name+",weight:"+this.weight);
}
public void draw(){
//some draw code which uses this.image
}
}
Where's your constructor? This isn't showing me enough to know if it's useful.
But after reading about Single responsibility principle and Open closed principle, I prefer separate a class into DTO and helper class with static methods only, eg:
public class CatData{
public String name;
public int weight;
public Image image;
}
public class CatMethods{
public static void printInfo(Cat cat){
System.out.println("Name:"+cat.name+",weight:"+cat.weight);
}
public static void draw(Cat cat){
//some draw code which uses cat.image
}
}
I think it fits Single responsibility principle because now the responsibility of CatData is to keep data only, doesn't care about the methods (also for CatMethods).
You can do many silly things in the name of the Single Responsibility Principle. I could argue that Cat Strings and Cat ints should be separated. That drawing methods and Images must all have their own class. That your running program is a single responsibility so you should only have one class. :P
To me, the best way to follow the Single Responsibility Principle is to find a good abstraction that lets you put complexity in a box so you can hide it. If you can give it a good name that keeps people from being surprised by what they find when they look inside you've followed it fairly well. Expecting it to dictate more decisions then that is asking for trouble. Honestly, both of your code listings do that so I don't see why SRP matters here.
And it also fits the open closed principle because adding new methods doesn't need to change the CatData class.
Well no. The open close principle isn't about adding new methods. It's about being able to change the implementation of old methods and having to edit nothing. Nothing that uses you and not your old methods. Instead you write some new code somewhere else. Some form of polymorphism will do that nicely. Don't see that here.
My question is, is it a good or an anti-pattern?
Well hell how should I know? Look, doing it either way has benefits and costs. When you separate code from data you can change either without having to recompile the other. Maybe that is critically important to you. Maybe it just makes your code pointlessly complicated.
If it makes you feel better you aren't that far from something Martin Fowler calls a parameter object. You don't have to only take primitives into your object.
What I would like you to do is develop a sense for how to do your separation, or not, in either coding style. Because believe it or not you're not being forced to choose a style. You just have to live with your choice.